package scheduler.fixtures;

import fitlibrary.DoFixture;
import fit.Fixture;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import javax.ejb.CreateException;
import javax.ejb.EJBContext;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import se392.ateam2006.meetingmgmt.MeetingMgmtRemote;
import se392.ateam2006.meetingmgmt.meeting.MeetingEntity;
import se392.ateam2006.resourcemgmt.ResourceMgmtRemote;
import se392.ateam2006.resourcemgmt.participant.ParticipationEntity;
import se392.ateam2006.resourcemgmt.participant.exclusionset.ExclusionRangeEntity;
import se392.ateam2006.user.UserEntity;
import se392.ateam2006.user.UserMgmtRemote;


/**
 * Main Fitnesse class.
 * This class acts as the contact point for most of the operations
 * in Fitnesse.
 * @author Ateam (Matthew Bennett, Claire Melton, Shingai Manyiwa, John Adderley)
 * @version 25/03/07
 */
public class StartApplication extends DoFixture {
    
    //private ManagementRemoteHome home;
    private MeetingMgmtRemote meetingManage;
    private ResourceMgmtRemote resourceManage;
    private UserMgmtRemote userManage;
    
    /**
     * Creates a new instance of StartApplication.
     * Sets up a connection between the fitnesse tables and the application
     * server.
     */
    public StartApplication() {
        
        System.setProperty("org.omg.CORBA.ORBInitialHost", "localhost");
        System.setProperty("org.omg.CORBA.ORBInitialPort", "3700");
        
        try {
            InitialContext jndicontext = new InitialContext();
            meetingManage = (MeetingMgmtRemote)jndicontext.lookup("se392.ateam2006.meetingmgmt.MeetingMgmtRemote");
            
            resourceManage = (ResourceMgmtRemote)jndicontext.lookup("se392.ateam2006.resourcemgmt.ResourceMgmtRemote");
            
            userManage = (UserMgmtRemote)jndicontext.lookup("se392.ateam2006.user.UserMgmtRemote");
            
        } catch (NamingException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        
        resourceManage.setTestingMode(true);
        
    }
    
    public Fixture setUpVenues(){
        return new SetUpVenues(resourceManage);
    }
    
    public Fixture setUpVenueOwnership(){
        return new SetUpVenueOwnership(resourceManage);
    }
    
    public Fixture setUpEquipment(){
        return new SetUpEquipment(resourceManage);
    }
    
    public Fixture setUpEquipmentOwnership(){
        return new SetUpEquipmentOwnership(resourceManage);
    }
    
    public Fixture setUpEmails(){
        return new SetUpEmails(userManage);
    }
    
    
    /**
     * Sets the "Current" time. 
     * Whenever the system requests the current time, a faked time should
     * be returned corresponding to the string last entered into this
     * method.
     */
    public void timeIsNow(String time){
        
        String[] dateTime = time.split(" ");
        String[] startDateArray = dateTime[0].split("/");
        String[] startTimeArray = dateTime[1].split(":");
        Calendar start = Calendar.getInstance();
        start.set(Integer.parseInt(startDateArray[0]),
                (Integer.parseInt(startDateArray[1])-1), // Jan starts at 0!
                Integer.parseInt(startDateArray[2]),
                Integer.parseInt(startTimeArray[0]),
                Integer.parseInt(startTimeArray[1]));
        start.set(Calendar.SECOND, 0);
        start.set(Calendar.MILLISECOND, 0);
        
        System.out.println("MANUTIME: String = " + time + ", date says " + start.getTime());
        resourceManage.setTestDate(start.getTime());
        //return false;
    }
    
    public Fixture createMeeting(){
        return new CreateMeeting(meetingManage, resourceManage, userManage);
    }
    
    public Fixture participantsForMeeting(String meetingId) {
        return new ParticipantsForMeeting(resourceManage, meetingManage, meetingId);
    }
    
    //TODO: must refactor
    public boolean submitExclusionSetForParticipantForMeetingWithStartDateAndEndDate(String email,
            String meetingID,
            String startDate,
            String endDate){
        
        UserEntity user = userManage.getUserByID(email);
        MeetingEntity meeting = meetingManage.findMeetingById(meetingID);
        
        
        ParticipationEntity pe = resourceManage.getParticipant(user, meeting);
        
        String[] startDateTime = startDate.split(" ");
        String[] endDateTime = endDate.split(" ");
        String[] startDateArray = startDateTime[0].split("/");
        String[] startTimeArray = startDateTime[1].split(":");
        String[] endDateArray = endDateTime[0].split("/");
        String[] endTimeArray = endDateTime[1].split(":");
        Calendar start = Calendar.getInstance();
        start.set(Integer.parseInt(startDateArray[0]),
                (Integer.parseInt(startDateArray[1])-1), // Jan starts at 0!
                Integer.parseInt(startDateArray[2]),
                Integer.parseInt(startTimeArray[0]),
                Integer.parseInt(startTimeArray[1]));
        Calendar end = Calendar.getInstance();
        end.set(Integer.parseInt(endDateArray[0]),
                (Integer.parseInt(endDateArray[1])-1), // Jan starts at 0!
                Integer.parseInt(endDateArray[2]),
                Integer.parseInt(endTimeArray[0]),
                Integer.parseInt(endTimeArray[1]));
        
        start.set(Calendar.SECOND,0);
        end.set(Calendar.SECOND,0);
        start.set(Calendar.MILLISECOND, 0);
        end.set(Calendar.MILLISECOND, 0);
        ExclusionRangeEntity ere = null;
        
        try {
            ere = resourceManage.createExclusionRangeEntity(user,meeting,start,end,false);
        }catch(CreateException e) {
            System.out.println("Failed to create Exclusion range: " + e.getMessage() +
                    "\nMStart: \t" + meeting.getStartDateRange().getTime() +
                    " MEnd: \t" + meeting.getEndDateRange().getTime() +
                    "\nExcStart: \t" + start.getTime() +
                    " ExcEnd: \t" + end.getTime());
            e.printStackTrace();
        }
        
        Collection<ExclusionRangeEntity> participations = resourceManage.getExclusionSetsForParticipant(user);
        
        if(participations.contains(ere)) {
            return true;
        } else {
            
            return false;
        }
        
        //pe.
        //SubmitResponse sr =  new SubmitResponse(manage, email, meetingID, startDate, endDate);
        //return sr.submitResponseWithExclsuionSets();
    }
    
    //TODO: must refactor
    public boolean submitPreferenceSetForParticipantForMeetingWithStartDateAndEndDate(String email,
            String meetingID,
            String startDate,
            String endDate){
        
        UserEntity user = userManage.getUserByID(email);
        MeetingEntity meeting = meetingManage.findMeetingById(meetingID);
        
        
        ParticipationEntity pe = resourceManage.getParticipant(user, meeting);
        
        String[] startDateTime = startDate.split(" ");
        String[] endDateTime = endDate.split(" ");
        String[] startDateArray = startDateTime[0].split("/");
        String[] startTimeArray = startDateTime[1].split(":");
        String[] endDateArray = endDateTime[0].split("/");
        String[] endTimeArray = endDateTime[1].split(":");
        Calendar start = Calendar.getInstance();
        start.set(Integer.parseInt(startDateArray[0]),
                (Integer.parseInt(startDateArray[1])-1), // Jan starts at 0!
                Integer.parseInt(startDateArray[2]),
                Integer.parseInt(startTimeArray[0]),
                Integer.parseInt(startTimeArray[1]));
        Calendar end = Calendar.getInstance();
        end.set(Integer.parseInt(endDateArray[0]),
                (Integer.parseInt(endDateArray[1])-1), // Jan starts at 0!
                Integer.parseInt(endDateArray[2]),
                Integer.parseInt(endTimeArray[0]),
                Integer.parseInt(endTimeArray[1]));
        start.set(Calendar.SECOND,0);
        end.set(Calendar.SECOND,0);
        start.set(Calendar.MILLISECOND, 0);
        end.set(Calendar.MILLISECOND, 0);
        
        
        ExclusionRangeEntity ere = null;
        
        try {
            ere = resourceManage.createExclusionRangeEntity(user,meeting,start,end,true);
        }catch(CreateException e) {
            System.out.println("Failed to create Preference set: " + e.getMessage() +
                    "\nMStart: \t" + meeting.getStartDateRange().getTime() +
                    " MEnd: \t" + meeting.getEndDateRange().getTime() +
                    "\nPrefStart: \t" + start.getTime() +
                    " PrefEnd: \t" + end.getTime());
            e.printStackTrace();
        }
        
        Collection<ExclusionRangeEntity> participations = resourceManage.getExclusionSetsForParticipant(user);
        
        if(participations.contains(ere)) {
            return true;
        } else {
            
            return false;
        }
        
        //pe.
        //SubmitResponse sr =  new SubmitResponse(manage, email, meetingID, startDate, endDate);
        //return sr.submitResponseWithExclsuionSets();
    }
    
    /*
    public boolean submitPreferenceSetForParticipantForMeetingWithStartDateAndEndDate(String email,
            String meetingID,
            String startDate,
            String endDate){
     
        //SubmitResponse sr =  new SubmitResponse(manage, email, meetingID, startDate, endDate);
        //return sr.submitResponseWithPreferenceSets();
    }
     */
    public void addParticipantTo(String status, String userId, String meetingId) throws Exception{
        boolean theStatus = false;
        
        if(status.equals("active")){
            theStatus = true;
        }else if(status.equals("normal")){
            theStatus = false;
        }else{
            throw new Exception();
        }
        ParticipationEntity part = resourceManage.createParticipation(meetingManage.findMeetingById(meetingId),
                userManage.getUserByID(userId), theStatus);
        
    }
    
    public Fixture plannedMeetings(){
        return new PlannedMeetings(meetingManage);
    }
    
    public void initiatorIdStartDateRangeEndDateRangeDurationTitleDescriptionVenueSize(String initiator, String id, String startDateRange,
            String endDateRange, String duration, String title, String description, String venue, int size) throws Exception {
        CreateMeeting createMeeting = new CreateMeeting(meetingManage, resourceManage, userManage);
        createMeeting.initiatorIdStartDateRangeEndDateRangeDurationTitleDescriptionVenueSize(initiator, id, startDateRange,
                endDateRange, duration, title, description, venue, size);
    }
    
    public int activeParticipantNumberFor(String id){
        return resourceManage.getActiveParticipantCount(meetingManage.findMeetingById(id));
    }
    
    public int allParticipantNumberFor(String id){
        return resourceManage.getMeetingParticipantCount(meetingManage.findMeetingById(id));
    }
    
    public boolean removeFrom(String userId, String meetingId){
        try {
            
            resourceManage.removeParticipation(
                    resourceManage.getParticipant(
                    userManage.getUserByID(userId), meetingManage.findMeetingById(meetingId)
                    )
                    );
            
            return true;
            
        } catch (IllegalArgumentException ex) {
            ex.printStackTrace();
            return false;
        }
        
    }
//
//    public Fixture exclusionSetForParticipantForMeeting(String email, String meetingId){
//        return new ExclusionSetForParticipantForMeeting(manage,email,meetingId);
//    }
//
//
//    public Fixture preferenceSetForParticipantForMeeting(String email, String meetingId){
//        return new PreferenceSetForParticipantForMeeting(manage,email,meetingId);
//    }
//
//    public Fixture exlusionSetForMeeting(String meetingId){
//        return new ExclusionSetsForMeeting(manage, meetingId);
//    }
//
//    public Fixture preferenceSetForMeeting(String meetingId){
//        return new PreferenceSetsForMeeting(manage, meetingId);
//    }
//
//    public Fixture preferenceSetForParticipant(String userId){
//        return new PreferenceSetsForParticipant(manage, userId);
//    }
//
//    public Fixture exclusionSetForParticipant(String userId){
//        return new ExclusionSetsForParticipant(manage, userId);
//    }
//
    public int meetingCount(){
        int size = -1024;
        
        try {
            size = meetingManage.getMeetingCount();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return size;
    }
    
    public Fixture removeAllMeetings(){
        return new RemoveAllMeetings(meetingManage);
    }
    
    public Fixture removeAllEquipment(){
        return new RemoveAllEquipment(resourceManage);
    }
    
    public Fixture removeAllVenues(){
        return new RemoveAllVenues(resourceManage);
    }
    
    public Fixture removeAllUsers(){
        return new RemoveAllUsers(userManage);
    }
    
    public Fixture removeAllExclusionSets(){
        return new RemoveAllExclusionSets(resourceManage);
    }
    
//    public Fixture removeAllDefaultMeetingStartTimes(){
//        return new  RemoveAllDefaultMeetingStartTimes(manage);
//    }
//
//    public int defaultMeetingStartTimesCount(){
//        int size = 0;
//        try {
//            size = manage.getDefaultMeetingStartTimesCount();
//        } catch (RemoteException ex) {
//            ex.printStackTrace();
//        }
//
//        return size;
//    }
//
    public int equipmentCount(){
        //TODO: actually implement
        int size = 0;
        return size;
    }
    
    public int venueCount(){
        return resourceManage.getRoomCount();
    }
    
    public int userCount(){
        return userManage.getUserCount();
    }
    
    public int exclusionSetsCount(){
        return resourceManage.getExclusionSetsCount();
    }
    
    public Fixture setUpBookingPermissions() {
        return new SetUpBookingPermissions(userManage);
    }
    
    
    public boolean setCutOffPeriodAsDay(int days){
        try{
            meetingManage.setDefaultCutOffPeriod(days);
            return true;
        }catch(Exception e){
            return false;
        }
    }
//
//    public boolean setWorkingDayStartAndEnd(String startDate, String endDate){
//
//        SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
//        Date time;
//
//        try {
//            time = sdf.parse(startDate);
//        } catch (ParseException ex) {
//            return false;
//        }
//
//        GregorianCalendar date = new GregorianCalendar();
//        date.setTime(time);
//
//        try{
//            manage.setWorkingDayStart(date);
//
//            time = sdf.parse(endDate);
//            date = new GregorianCalendar();
//            date.setTime(time);
//
//            manage.setWorkingDayEnd(date);
//            return true;
//
//        }catch(Exception e){
//            return false;
//        }
//    }
//
//    public boolean setUpWorkingWeekDays(String d){
//
//        try{
//            String days = SystemUtils.dayStringBuilder(d);
//            manage.setWorkingDays(days);
//            return true;
//
//        }catch(Exception e){
//            return false;
//        }
//    }
//
//    public boolean setUpMeetingStartTimesForPeriodStartTimePeriodEndTimeOffset(String startTime, String endTime, int offset){
//        SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
//        Date sTime;
//        Date eTime;
//
//        try {
//            sTime = sdf.parse(startTime);
//            eTime = sdf.parse(endTime);
//        } catch (ParseException ex) {
//            return false;
//        }
//
//        GregorianCalendar startDate = new GregorianCalendar();
//        startDate.setTime(sTime);
//        GregorianCalendar endDate = new GregorianCalendar();
//        endDate.setTime(eTime);
//
//        DefaultMeetingStartTimesDTO dto = new DefaultMeetingStartTimesDTO(startDate, endDate, offset);
//
//        try{
//            manage.setMeetingStartPeriods(dto);
//        }catch(Exception e){
//            return false;
//        }
//
//        return true;
//    }
//
//    public boolean removeAllExclusionSetsForMeeting(String meetingID){
//        try{
//            manage.removeExclusionSetsByMeetingId(meetingID);
//            manage.removePreferenceSetsByMeetingId(meetingID);
//            return true;
//        }catch(Exception e){
//            return false;
//        }
//    }
//
//    public boolean submitEquipmentRequestForParticipantForMeetingEquipmentTypeNumber(String userId, String meetingId, String equipmentType, int number){
//        try{
//            manage.addEquipmentConstraint(new EquipmentConstraintsDTO(userId, meetingId, equipmentType, number));
//            return true;
//        }catch(Exception e){
//            System.err.println("check me here");
//            e.printStackTrace();
//            return false;
//        }
//    }
//
//    public Fixture equipmentConstraintsForParticipantForMeeting(String userId, String meetingId){
//        return new EquipmentConstraintsForParticipantForMeeting(manage, userId, meetingId);
//    }
//
//    public Fixture calculateDateTimeVenueForMeeting(String meetingId){
//        return new CalculateDateTimeVenueForMeeting(manage, meetingId);
//    }
//
//    public boolean bookMeetingAtDateTimeVenue(String meetingId, String theStartDate, String venue){
//
//        try{
//
//            SimpleDateFormat format = new SimpleDateFormat("yyyy/MM/dd kk:mm");
//            Date startDate = format.parse(theStartDate);
//            manage.bookMeeting(meetingId, venue, startDate);
//            return true;
//        }catch(Exception ex){
//            ex.printStackTrace();
//            return false;
//        }
//    }
//
//    public Fixture bookedMeetings(){
//        return new BookedMeetings(manage);
//    }
//
//    public boolean unbookMeeting(String meetingId){
//        try{
//            manage.unbookMeeting(meetingId);
//            return true;
//        }catch(Exception ex){
//            return false;
//        }
//    }
//
//    public boolean removeAllEquipmentRequirementsForMeeting(String meetingID){
//        try{
//            manage.removeEquipmentRequirementsForMeeting(meetingID);
//            return true;
//        }catch(Exception e){
//            return false;
//        }
//    }
}
